<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <link rel="shortcut icon" href="favicon.ico"/>

    <script src="vendor/d3/d3-3.3.4.js"></script>
    <script src="vendor/react/react.js"></script>
    <script src="vendor/react/JSXTransformer.js"></script>

    <link href="vendor/bootstrap/css/bootstrap.css" rel="stylesheet" type="text/css">

    <style type="text/css">
        .no-queries {
            text-align: center;
            margin-top: 10px;
        }
        .no-queries h4 {
            margin: 0;
        }
        .toolbar {
            padding: 3px;
            background-color: #eee;
        }
        .toolbar label {
            margin: 0;
        }
        .sql {
            word-wrap: break-word;
            white-space: normal;
        }
        .query-row {
            padding: 6px;
            border-top: 1px solid #bbb;
        }
        .row {
            white-space: nowrap;
        }
        .truncate {
            overflow: hidden;
            text-overflow: ellipsis;
        }
        pre {
            margin: 0;
        }
        .header {
            background-color: black;
            padding-bottom: 10px;
            color: #cccccc;
        }
        .logo {
            height: 50px;
        }
        .bg-success-warning {
            background-color: #EEF4DF;
        }
        .bg-danger-warning {
            background-color: #F7EBE1;
        }
        .bg-info-light {
            background-color: #EBF3F7;
        }
        .text-right {
            text-align: right;
        }
    </style>
</head>

<body>

<div class="container-fluid">
    <div class="row header">
        <div class="col-md-9">
            <a href=".">
                <img class="logo" alt="Presto logo" src="./presto.png" />
            </a>
        </div>
        <div class="col-md-3 text-right" id="version"></div>
        <div class="col-md-3 text-right" id="environment"></div>
    </div>

    <div id="queries"></div>
</div>

<script type="text/jsx">
d3.json("/v1/info", function (info) {
    document.getElementById('version').textContent = "Version: " + info.nodeVersion.version;
    document.getElementById('environment').textContent = info.environment;
});

var Query = React.createClass({
    shortErrorType: function(errorType, errorCode)
    {
        switch (errorType) {
            case "USER_ERROR":
                if (errorCode.name === 'USER_CANCELED') {
                    return "USER CANCELED";
                }
                return "USER ERROR";
            case "INTERNAL_ERROR":
                return "INTERNAL ERROR";
            case "INSUFFICIENT_RESOURCES":
                return "INSUFFICIENT RESOURCES";
            case "EXTERNAL":
                return "EXTERNAL ERROR";
        }
        return errorType;
    },
    stateClass: function(state, errorType, errorCode)
    {
        switch (state) {
            case "FINISHED":
                return "bg-success";
            case "FAILED":
                switch (errorType) {
                    case "USER_ERROR":
                        if (errorCode.name === 'USER_CANCELED') {
                            return "bg-warning";
                        }
                        return "bg-success-warning";
                    case "EXTERNAL":
                        return "bg-danger-warning";
                    case "INSUFFICIENT_RESOURCES":
                        return "bg-success-warning";
                    default:
                        return "bg-danger";
                }
            case "QUEUED":
                return "bg-info-light";
            default:
                return "bg-info";
        }
    },
    render: function()
    {
        var query = this.props.query;

        var progress = "N/A";
        if (query.scheduled) {
            progress = d3.format("%")(query.totalDrivers == 0 ? 0 : query.completedDrivers / query.totalDrivers);
        }
        var state = query.state;
        if (state === "FAILED") {
            state = this.shortErrorType(query.errorType, query.errorCode);
        }
        if (query.fullyBlocked && state == "RUNNING") {
            state = "BLOCKED";
            if (query.blockedReasons.length > 0) {
                state += " (" + query.blockedReasons.join() + ")";
            }
        }
        var splits;
        if (query.state == 'FINISHED' || query.state == 'FAILED') {
            splits = <div className="row">
                <div className="col-md-12">
                    Completed Splits: {query.completedDrivers}
                </div>
            </div>
        }
        else {
            splits = <div className="row">
                <div className="col-md-4">
                    Queued: {query.queuedDrivers}
                </div>
                <div className="col-md-4">
                    Running: {query.runningDrivers}
                </div>
                <div className="col-md-4">
                    Done: {query.completedDrivers}
                </div>
            </div>;
        }
        var authenticatedIcon = "";
        if (query.session.principal) {
            authenticatedIcon = <span className="glyphicon glyphicon-lock"></span>;
        }
        var queryText = query.query;
        if (queryText.length > 200) {
            queryText = queryText.substring(0, 200) + "...";
        }
        return (
                <div className={"row query-row " + this.stateClass(query.state, query.errorType, query.errorCode)}>
                    <div className="col-md-3 col-lg-3">
                        <div className="row">
                            <div className="col-md-12"><a href={"query.html?" + query.queryId}>{query.queryId}</a></div>
                        </div>
                        <div className="row">
                            <div className="col-md-12 truncate">
                                <span>{query.session.user} {authenticatedIcon}</span>
                            </div>
                        </div>
                        <div className="row">
                            <div className="col-md-12 truncate">{query.session.source}</div>
                        </div>
                    </div>
                    <div className="col-md-4 col-lg-3">
                        <div className="row">
                            <div className="col-md-8">{query.elapsedTime} ({progress})</div>
                        </div>
                        <div className="row">
                            <div className="col-md-12">{state}</div>
                        </div>
                        {splits}
                    </div>
                    <div className="col-md-5 col-lg-6"><pre><code className="sql">{queryText}</code></pre></div>
                </div>
        );
    }
});

var QueryList = React.createClass({
    render: function()
    {
        var queryNodes = this.props.queries.map(function (query) {
            return (
                    <Query key={query.queryId} query={query} />
            );
        }.bind(this));
        return (
                <div>
                    {queryNodes}
                </div>
        );
    }
});

var QueryPane = React.createClass({
    getInitialState: function() {
        return {queries: [], autoRefresh: true, initialized: false};
    },
    refreshLoop: function() {
        clearTimeout(this.timeoutId); // to stop multiple series of refreshLoop from going on simultaneously
        d3.json('/v1/query', function (queries) {
            if (!this.state.autoRefresh) { // to stop refreshing when user turns off auto-refresh at the same time json was being fetched
                return;
            }
            this.setState({queries: queries, initialized: true});
            clearTimeout(this.timeoutId); // to stop multiple series of refreshLoop from going on simultaneously
            this.timeoutId = setTimeout(this.refreshLoop, 1000);
        }.bind(this));
    },
    componentDidMount: function() {
        window.addEventListener('keydown', this.handleKeyDown, false);
        this.refreshLoop();
    },
    componentDidUpdate: function(prevProps, prevState) {
        if (prevState.autoRefresh != this.state.autoRefresh) {
            if (this.state.autoRefresh) {
                this.refreshLoop();
            }
            else {
                clearTimeout(this.timeoutId);
            }
        }
    },
    handleKeyDown: function(event) {
        if (event.keyCode === 90) { // z-key
            this.setState({autoRefresh: !this.state.autoRefresh});
        }
    },
    handleAutoRefresh: function(event) {
        this.setState({autoRefresh: event.target.checked});
    },
    render: function() {
        if (this.state.queries !== null && this.state.queries.length > 0) {
            var runningQueries = [];
            var doneQueries = [];
            runningQueries = this.state.queries.filter(function (query) {
                return query.state != 'FINISHED' && query.state != 'FAILED';
            });

            doneQueries = this.state.queries.filter(function (query) {
                return query.state == 'FINISHED' || query.state == 'FAILED';
            });
            runningQueries.sort(function(a, b) { return d3.descending(a.createTime, b.createTime); });
            doneQueries.sort(function(a, b) { return d3.descending(a.endTime, b.endTime); });
            return (
                    <div>
                        <div className="row toolbar">
                            <div className="col-md-12">
                                <label><input type="checkbox" checked={this.state.autoRefresh} onChange={this.handleAutoRefresh} /> auto-refresh</label>
                            </div>
                        </div>
                        <QueryList queries={runningQueries} />
                        <QueryList queries={doneQueries} />
                    </div>
            );
        }
        else {
            var label = this.state.initialized ? "No queries" : "Loading...";
            return (
                    <div className="row no-queries">
                        <div className="col-md-12"><div className="well"><h4>{label}</h4></div></div>
                    </div>
            );
        }
    }
});
React.render(
        <QueryPane />,
        document.getElementById('queries')
);
</script>

</body>
</html>
